#include "TM8211.h"

static void TM8211_delay_us(uint32_t nus)
{
//    volatile uint32_t ticks;
//    volatile uint32_t told, tnow, tcnt = 0;
//    volatile uint32_t reload = SysTick->LOAD;
//    ticks = nus * reload / 1000;
//    told = SysTick->VAL;
//    while (1)
//    {
//        tnow = SysTick->VAL;
//        if (tnow != told)
//        {
//            if (tnow < told)
//                tcnt += told - tnow;
//            else
//                tcnt += reload - tnow + told;
//            told = tnow;
//            if (tcnt >= ticks)
//                break;
//        }
//    };
}

static void TM8211_write_dat(TM8211_t *tm8211, uint16_t data)
{
    uint8_t i;
    for (i = 0; i < 16; i++)
    {
        HAL_GPIO_WritePin(tm8211->BCK_port, tm8211->BCK_pin, GPIO_PIN_RESET);
        if ((data >> (15 - i)) & 0x0001)
            HAL_GPIO_WritePin(tm8211->DIN_port, tm8211->DIN_pin, GPIO_PIN_SET);
        else
            HAL_GPIO_WritePin(tm8211->DIN_port, tm8211->DIN_pin, GPIO_PIN_RESET);

        TM8211_delay_us(TM8211_DELAY_TIME);
        HAL_GPIO_WritePin(tm8211->BCK_port, tm8211->BCK_pin, GPIO_PIN_SET);
        TM8211_delay_us(TM8211_DELAY_TIME);
    }
}

static void TM8211_output_config(TM8211_t *tm8211)
{
    HAL_GPIO_WritePin(tm8211->WS_port, tm8211->WS_pin, GPIO_PIN_RESET);
    TM8211_delay_us(TM8211_DELAY_TIME);
    TM8211_write_dat(tm8211, tm8211->ch1_val);

    TM8211_delay_us(TM8211_DELAY_TIME);

    HAL_GPIO_WritePin(tm8211->WS_port, tm8211->WS_pin, GPIO_PIN_SET);
    TM8211_delay_us(TM8211_DELAY_TIME);
    TM8211_write_dat(tm8211, tm8211->ch2_val);

    TM8211_delay_us(TM8211_DELAY_TIME);
    HAL_GPIO_WritePin(tm8211->WS_port, tm8211->WS_pin, GPIO_PIN_RESET);
}

void TM8211_set_ch_volt(TM8211_t *tm8211, tm8211_ch_t ch, uint16_t volt)
{
    float min_volt = tm8211->ref_volt * 0.25;
    float max_volt = tm8211->ref_volt * 0.75;
    float bit_ref = (float)65536 / (max_volt - min_volt);
    uint16_t out_val = 0x8000;

    if (volt > min_volt)
    {
        out_val += (volt - min_volt) * bit_ref;
    }
    if (ch == TM8211_CH1)
    {
        tm8211->ch1_val = out_val;
    }
    if (ch == TM8211_CH2)
    {
        tm8211->ch2_val = out_val;
    }
    TM8211_output_config(tm8211);
}
